package com.ymx.darling.log.jdbc;

import com.ymx.darling.log.Log;
import com.ymx.darling.util.ArrayUtil;

import java.lang.reflect.Method;
import java.sql.Array;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 爱Java的小于
 */
public abstract class BaseJdbcLogger {
    protected static final Set<String> SET_METHODS = Arrays.stream(PreparedStatement.class.getDeclaredMethods()).filter((method) -> method.getName().startsWith("set")).filter((method) -> method.getParameterCount() > 1).map(Method::getName).collect(Collectors.toSet());
    protected static final Set<String> EXECUTE_METHODS = new HashSet<>();
    private final Map<Object, Object> columnMap = new HashMap<>();
    private final List<Object> columnValues = new ArrayList<>();
    protected final Log logger;

    public BaseJdbcLogger(Log log) {
        this.logger = log;
    }

    public Log getStatementLogger() {
        return logger;
    }

    protected void setColumn(Object key, Object value) {
        this.columnMap.put(key, value);
        this.columnValues.add(value);
    }

    protected Object getColumn(Object key) {
        return this.columnMap.get(key);
    }

    protected String getParameterValueString() {
        List<Object> typeList = new ArrayList<>(this.columnValues.size());

        for (Object value : this.columnValues) {
            if (value == null) {
                typeList.add("null");
            } else {
                typeList.add(this.objectValueString(value) + "(" + value.getClass().getSimpleName() + ")");
            }
        }

        String parameters = typeList.toString();
        return parameters.substring(1, parameters.length() - 1);
    }

    protected String objectValueString(Object value) {
        if (value instanceof Array) {
            try {
                return ArrayUtil.toString(((Array)value).getArray());
            } catch (SQLException ignored) {}
        }

        return value.toString();
    }

    protected void clearColumnInfo() {
        this.columnMap.clear();
        this.columnValues.clear();
    }

    protected boolean isDebugEnabled() {
        return this.logger.isDebugEnabled();
    }

    protected boolean isTraceEnabled() {
        return this.logger.isTraceEnabled();
    }

    protected void debug(String text, boolean input) {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug(this.prefix(input) + text);
        }

    }

    protected void trace(String text, boolean input) {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace(this.prefix(input) + text);
        }

    }

    private String prefix(boolean isInput) {
        return isInput ? "==>" : "<==";
    }

    static {
        EXECUTE_METHODS.add("execute");
        EXECUTE_METHODS.add("addBatch");
        EXECUTE_METHODS.add("executeUpdate");
        EXECUTE_METHODS.add("executeQuery");
    }
}

